package com.open.demo.apm

import com.tencent.matrix.trace.core.AppMethodBeat
import com.tencent.matrix.trace.core.AppMethodBeat.IndexRecord
import com.tencent.matrix.trace.listeners.LooperObserver

/**
  #方案
   业内主要框架的主要思想是，监控主线程执行耗时，当超过阈值时，dump出当前主线程的执行堆栈，通过堆栈分析找到卡顿原因。
  #监控原理
   依赖主线程 Looper，监控每次 dispatchMessage 的执行耗时。（BlockCanary）
   依赖 Choreographer 模块，监控相邻两次 Vsync 事件通知的时间差。（ArgusAPM、LogMonitor）
  * https://nelsonblog.me/2019/10/14/%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E4%B9%8BMatrix/
  *
  *
  * https://github.com/Tencent/matrix/wiki/Matrix-Android-TraceCanary
 */
class Tracer : LooperObserver() {

    override fun dispatchBegin(beginNs: Long, cpuBeginNs: Long, token: Long) {
        super.dispatchBegin(beginNs, cpuBeginNs, token)
        AppMethodBeat.getInstance().maskIndex("EvilMethodTracer#dispatchBegin")
    }

    override fun doFrame(
        focusedActivity: String?,
        startNs: Long,
        endNs: Long,
        isVsyncFrame: Boolean,
        intendedFrameTimeNs: Long,
        inputCostNs: Long,
        animationCostNs: Long,
        traversalCostNs: Long
    ) {
        super.doFrame(focusedActivity, startNs, endNs, isVsyncFrame, intendedFrameTimeNs, inputCostNs, animationCostNs, traversalCostNs)
    }

    private var indexRecord: IndexRecord? = null

    override fun dispatchEnd(beginNs: Long, cpuBeginMs: Long, endNs: Long, cpuEndMs: Long, token: Long, isVsyncFrame: Boolean) {
        super.dispatchEnd(beginNs, cpuBeginMs, endNs, cpuEndMs, token, isVsyncFrame)
        val dispatchCost = (endNs - beginNs) / SysUtils.TIME_MILLIS_TO_NANO
        if (dispatchCost > SysUtils.DEFAULT_EVIL_METHOD_THRESHOLD_MS) {
            val datas = AppMethodBeat.getInstance().copyData(indexRecord)
            val queueCosts = null
            System.arraycopy(queueCosts, 0, queueCosts, 0, 3)
            val scene = AppMethodBeat.getVisibleScene()
            // isForeground, scene, data, queueCosts, cpuEndMs - cpuBeginMs, dispatchCost, endNs / SysUtils.TIME_MILLIS_TO_NANO
            ApmHandlerThread.handler?.post(AnalyseTask())
        }
    }

    fun isAlive(): Boolean {return false}

    fun onStartTrace() {}

    fun onCloseTrace() {}

    fun onForeground(isForeground: Boolean) {}

    class AnalyseTask : Runnable {
        override fun run() {
        }
    }
}

/*
在dispatchBegin方法中，记录下AppMethodBeat中目前的index，记为start；
在dispatchEnd中，读取目前AppMethodBeat中目前的index，记为end。
这两者中间的数据则为这段时间内执行的方法的入栈、出栈信息。
当这个Message执行时间超过指定的阈值（默认700ms）时，认为可能发生了慢方法，此时会进行进一步的分析。
至于doFrame中记录的数据，没有啥具体的用处，这是在最后打印了log而已。
 */